package com.nulldev.util.web.YouTubeExtractor.formats.ecd.codecs;

import com.nulldev.util.VariableAPI.StringsUtil;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;

public enum VideoCodecs {

	/*
	 * Work in progress: YouTubeExtractor Extension: ECD (Enhanced Codec Data)
	 */

	UNKNOWN("N/A", 0, "N/A", "N/A"),

	/* MPEG4 Visual */

	MPEG4_VISUAL_SIMPLE_L0("mp4v.20.3", 0, "Simple", "MPEG4 Visual (MPEG4/H.263/MPEG-4 Part 2) Simple Profile, Level 0"),

	/* h264 */

	H264_CONSTRAINED_MAIN_LEVEL_1("avc1.4d400a", 1.0, "Constrained Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Constrained Main, Level 1.0"),
	H264_CONSTRAINED_MAIN_LEVEL_1_1("avc1.4d400b", 1.1, "Constrained Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Constrained Main, Level 1.1"),
	H264_CONSTRAINED_MAIN_LEVEL_1_2("avc1.4d400c", 1.2, "Constrained Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Constrained Main, Level 1.2"),
	H264_CONSTRAINED_MAIN_LEVEL_1_3("avc1.4d400d", 1.3, "Constrained Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Constrained Main, Level 1.3"),
	H264_CONSTRAINED_MAIN_LEVEL_2_1("avc1.4d4015", 2.1, "Constrained Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Constrained Main, Level 2.1"),
	H264_CONSTRAINED_MAIN_LEVEL_2_2("avc1.4d4016", 2.2, "Constrained Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Constrained Main, Level 2.2"),
	H264_CONSTRAINED_MAIN_LEVEL_3_0("avc1.4d401e", 3.0, "Constrained Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Constrained Main, Level 3.0"),
	H264_CONSTRAINED_MAIN_LEVEL_3_1("avc1.4d401f", 3.1, "Constrained Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Constrained Main, Level 3.1"),
	H264_CONSTRAINED_MAIN_LEVEL_3_2("avc1.4d4020", 3.2, "Constrained Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Constrained Main, Level 3.2"),
	H264_BASELINE_LEVEL1("avc1.42c00b", 1.0, "Baseline (??)", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Baseline, Level 1 (??)"),
	H264_BASELINE_LEVEL2("avc1.42c00c", 2.0, "Baseline (??)", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Baseline, Level 2 (??)"),
	H264_BASELINE_LEVEL3("avc1.42E01E", 3.0, "Baseline", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Baseline, Level 3"),
	H264_BASELINE_LEVEL3_E("avc1.42001E", 3.0, "Baseline", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Baseline, Level 3"),
	H264_BASELINE_LEVEL3_1("avc1.42E01F", 3.1, "Baseline", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Baseline, Level 3.1"),
	H264_MAIN_LEVEL3("avc1.4D401E", 3, "Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Main, Level 3"),
	H264_MAIN_LEVEL_3_1("avc1.4D401F", 3.1, "Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), Main, Level 3.1"),
	H264_MAIN_LEVEL4("avc1.4D4028", 4, "Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), High, Level 4"),
	H264_MAIN_LEVEL4_1("avc1.640029", 4.1, "Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), High, Level 4.1"),
	H264_MAIN_LEVEL4_2("avc1.64002a", 4.2, "Main", "h264 (AVC/MPEG-4/MPEG-4 Part 10), High, Level 4.2"),
	H264_HIGH_LEVEL_3_1("avc1.64001F", 3.1, "High", "h264 (AVC/MPEG-4/MPEG-4 Part 10), High, Level 3.1"),
	H264_HIGH_LEVEL_3_2("avc1.640020", 3.2, "High", "h264 (AVC/MPEG-4/MPEG-4 Part 10), High, Level 3.2"),
	H264_HIGH_LEVEL3("avc1.64001E", 3, "High", "h264 (AVC/MPEG-4/MPEG-4 Part 10), High, Level 3"),
	H264_HIGH_LEVEL4("avc1.640028", 4, "High", "h264 (AVC/MPEG-4/MPEG-4 Part 10), High, Level 4"),
	H264_HIGH_LEVEL_4_1("avc1.640029", 4.1, "High", "h264 (AVC/MPEG-4/MPEG-4 Part 10), High, Level 4.1"),

	/* vp9 (generic) */

	VP9_PROFILE_0("vp9", 0, "Profile 0", "VP9 (Google VP9), Profile 0"),
	VP9_PROFILE_1("vp9.1", 1, "Profile 1", "VP9 (Google VP9), Profile 1"),
	VP9_PROFILE_2("vp9.2", 2, "Profile 2", "VP9 (Google VP9), Profile 2"),

	/* vp9 (profiles) */

	VP9_PROFILE_0_L1_1("vp09.00.11.08", 1.1, "Profile 0", "VP9 (Google VP9), Profile 0, Level 1.1"),
	VP9_PROFILE_0_L2("vp09.00.20.08", 2.0, "Profile 0", "VP9 (Google VP9), Profile 0, Level 2"),
	VP9_PROFILE_0_L2_1("vp09.00.21.08", 2.1, "Profile 0", "VP9 (Google VP9), Profile 0, Level 2.1"),
	VP9_PROFILE_0_L3("vp09.00.30.08", 3.0, "Profile 0", "VP9 (Google VP9), Profile 0, Level 3"),
	VP9_PROFILE_0_L3_1("vp09.00.31.08", 3.1, "Profile 0", "VP9 (Google VP9), Profile 0, Level 3.1"),
	VP9_PROFILE_0_L4("vp09.00.40.08", 4.0, "Profile 0", "VP9 (Google VP9), Profile 0, Level 4"),
	VP9_PROFILE_0_L5("vp09.00.50.08", 5.0, "Profile 0", "VP9 (Google VP9), Profile 0, Level 5"),
	VP9_PROFILE_0_L6("vp09.00.60.08", 6.0, "Profile 0", "VP9 (Google VP9), Profile 0, Level 6"),

	/* av01 */

	AV01_MAIN_8BPP_L2("av01.0.00M.08", 2.0, "Main Profile, 8bit, L2", "AV1 (AOMedia Video 1) Main Profile, Level 2.0, 8 bits"),
	AV01_MAIN_8BPP_L2_1("av01.0.01M.08", 2.1, "Main Profile, 8bit, L2.1", "AV1 (AOMedia Video 1) Main Profile, Level 2.1, 8 bits"),
	AV01_MAIN_8BPP_L3("av01.0.04M.08", 3.0, "Main Profile, 8bit, L3", "AV1 (AOMedia Video 1) Main Profile, Level 3.0, 8 bits"),
	AV01_MAIN_8BPP_L3_1("av01.0.05M.08", 3.1, "Main Profile, 8bit, L3.1", "AV1 (AOMedia Video 1) Main Profile, Level 3.1, 8 bits"),
	AV01_MAIN_8BPP_L4("av01.0.08M.08", 4.0, "Main Profile, 8bit, L4", "AV1 (AOMedia Video 1) Main Profile, Level 4.0, 8 bits"),
	AV01_MAIN_8BPP_L4_1("av01.0.09M.08", 4.1, "Main Profile, 8bit, L4.1", "AV1 (AOMedia Video 1) Main Profile, Level 4.1, 8 bits"),
	AV01_MAIN_8BPP_L5("av01.0.12M.08", 5.0, "Main Profile, 8bit, L5", "AV1 (AOMedia Video 1) Main Profile, Level 5.0, 8 bits"),
	AV01_MAIN_8BPP_L5_1("av01.0.13M.08", 5.1, "Main Profile, 8bit, L5.1", "AV1 (AOMedia Video 1) Main Profile, Level 5.1, 8 bits"),
	AV01_MAIN_8BPP_L6_0("av01.0.16M.08", 6.0, "Main Profile, 8bit, L6", "AV1 (AOMedia Video 1) Main Profile, Level 6.0, 8 bits"),
	AV01_MAIN_8BPP_L6("av01.0.17M.08", 6.0, "Main Profile, 8bit, L6", "AV1 (AOMedia Video 1) Main Profile, Level 6.0, 8 bits"),

	AV01_MAIN_10BPP_L2("av01.0.00M.10", 2.0, "Main Profile, 10bit, L2", "AV1 (AOMedia Video 1) Main Profile, Level 2.0, 10 bits"),
	AV01_MAIN_10BPP_L2_1("av01.0.01M.10", 2.1, "Main Profile, 10bit, L2.1", "AV1 (AOMedia Video 1) Main Profile, Level 2.1, 10 bits"),
	AV01_MAIN_10BPP_L3("av01.0.04M.10", 3.0, "Main Profile, 10bit, L3", "AV1 (AOMedia Video 1) Main Profile, Level 3.0, 10 bits"),
	AV01_MAIN_10BPP_L3_1("av01.0.05M.10", 3.1, "Main Profile, 10bit, L3.1", "AV1 (AOMedia Video 1) Main Profile, Level 3.1, 10 bits"),
	AV01_MAIN_10BPP_L4("av01.0.08M.10", 4.0, "Main Profile, 10bit, L4", "AV1 (AOMedia Video 1) Main Profile, Level 4.0, 10 bits"),
	AV01_MAIN_10BPP_L4_1("av01.0.09M.10", 4.1, "Main Profile, 10bit, L4.1", "AV1 (AOMedia Video 1) Main Profile, Level 4.1, 10 bits"),
	AV01_MAIN_10BPP_L5("av01.0.12M.10", 5.0, "Main Profile, 10bit, L5", "AV1 (AOMedia Video 1) Main Profile, Level 5.0, 10 bits"),
	AV01_MAIN_10BPP_L5_1("av01.0.13M.10", 5.1, "Main Profile, 10bit, L5.1", "AV1 (AOMedia Video 1) Main Profile, Level 5.1, 10 bits"),
	AV01_MAIN_10BPP_L6("av01.0.17M.10", 6.0, "Main Profile, 10bit, L6", "AV1 (AOMedia Video 1) Main Profile, Level 6.0, 10 bits"),;

	private final String codecString;
	private final double dIdent;
	private final String stringIdent;
	private final String fullCodecString;

	private VideoCodecs(final String codecString, final double identifier, final String stringIdentifier, final String fullCodecString) {
		this.codecString = codecString;
		this.dIdent = identifier;
		this.stringIdent = stringIdentifier;
		this.fullCodecString = fullCodecString;
	}

	public String getCodecString() {
		return this.codecString;
	}

	public double getDoubleIdentifier() {
		return this.dIdent;
	}

	public String getStringIdentifier() {
		return this.stringIdent;
	}

	public String getFullCodecString() {
		return this.fullCodecString;
	}

	private static final Logger log = LoggerFactory.getLogger();

	public static VideoCodecs fromMime(final String mime) {
		if (mime == null || mime.isEmpty())
			return UNKNOWN;
		if (!mime.startsWith("video/"))
			return UNKNOWN; // FIXME: We don't account for fallback videos.
		final String actualMime = StringsUtil.substringBetweenO(StringsUtil.cleanInvalidCharacters(mime), "\"", "\"");
		for (final VideoCodecs codec : values()) {
			if (codec.codecString.equalsIgnoreCase(actualMime) || actualMime.startsWith(codec.codecString))
				return codec;
		}
		log.warn("Unknown video codec mime: " + actualMime);
		return UNKNOWN;
	}
}
